import java.util.*;

import javafx.util.Pair;

/*
给定一个 n×m 的二维整数数组，用来表示一个迷宫，数组中只包含 0或 1，其中 0表示可以走的路，1表示不可通过的墙壁。
最初，有一个人位于左上角 (1,1) 处，已知该人每次可以向上、下、左、右任意一个方向移动一个位置。
请问，该人从左上角移动至右下角 (n,m)处，至少需要移动多少次。
数据保证 (1,1) 处和 (n,m) 处的数字为 0，且一定至少存在一条通路。

输入格式
第一行包含两个整数 n和 m。
接下来 n行，每行包含 m个整数（0或 1），表示完整的二维数组迷宫。

输出格式
输出一个整数，表示从左上角移动至右下角的最少移动次数。

数据范围
1≤n,m≤100

输入样例：
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

输出样例：
8
 */
//public class Main {
//    static int[][] map = new int[101][101];
//    static int[][] distance = new int[101][101];
//    static boolean[][] visited = new boolean[101][101];
//    static int n, m;
//
//    static void BFS() {
//        Queue<Pair<Integer, Integer>> q = new LinkedList<>();
//        q.add(new Pair<>(1, 1));
//        int[] dx = {0, 0, 1, -1};
//        int[] dy = {1, -1, 0, 0};
//        visited[0][0] = true;
//        while (!q.isEmpty()) {
//            Pair<Integer, Integer> p = q.poll();
//            int x = p.getKey(), y = p.getValue();
//            for (int i = 0; i < 4; i++) {
//                int newX = x + dx[i];
//                int newY = y + dy[i];
//                if (newX >= 1 && newX <= n && newY >= 1 && newY <= m && !visited[newX][newY] && map[newX][newY] == 0) {
//                    q.add(new Pair<>(newX, newY));
//                    visited[newX][newY] = true;
//                    distance[newX][newY] = 1 + distance[x][y];
//                }
//            }
//        }
//        System.out.println(distance[n][m]);
//    }
//
//    public static void main(String[] args) {
//        Scanner sc = new Scanner(System.in);
//        n = sc.nextInt();
//        m = sc.nextInt();
//        for (int i = 1; i <= n; i++) {
//            for (int j = 1; j <= m; j++) {
//                map[i][j] = sc.nextInt();
//            }
//        }
//        BFS();
//    }
//}

/*
给定一个 n个点 m条边的有向图，图中可能存在重边和自环。
所有边的长度都是 1，点的编号为 1∼n。
请你求出 1号点到 n号点的最短距离，如果从 1号点无法走到 n号点，输出 −1。

输入格式
第一行包含两个整数 n和 m。
接下来 m行，每行包含两个整数 a和 b，表示存在一条从 a走到 b的长度为 1 的边。

输出格式
输出一个整数，表示 1号点到 n号点的最短距离。

数据范围
1≤n,m≤1e5

输入样例：
4 5
1 2
2 3
3 4
1 3
1 4
 */
//public class Main {
//    static int n, m;//dots,edges
//    static ArrayList<ArrayList<Integer>> graph = new ArrayList<>();
//    static int[] distance = new int[10010];
//    static boolean[] visited = new boolean[10010];
//
//    static void addEdge(int v, int w) {
//        graph.get(v).add(w);
//    }
//
//    static void BFS(int v) {
//        Queue<Integer> q = new LinkedList<>();
//        q.add(v);
//        distance[v] = 0;
//        visited[v] = true;
//        while (!q.isEmpty()) {
//            int u = q.poll();
//            for (int e : graph.get(u)) {
//                if (!visited[e]) {
//                    q.add(e);
//                    distance[e] = distance[u] + 1;
//                    visited[e] = true;
//                }
//            }
//        }
//    }
//
//    public static void main(String[] args) {
//        Scanner sc = new Scanner(System.in);
//        for (int i = 0; i < 10005; i++) {
//            graph.add(new ArrayList<>());
//            distance[i] = -1;
//        }
//        n = sc.nextInt();
//        m = sc.nextInt();
//        for (int i = 0; i < m; i++) {
//            addEdge(sc.nextInt(), sc.nextInt());
//        }
//        BFS(1);
//        System.out.println(distance[n]);
//    }
//}

/*
拓扑排序
给定一个 n个点 m 条边的有向图，点的编号是 1 到 n，图中可能存在重边和自环。
请输出任意一个该有向图的拓扑序列，如果拓扑序列不存在，则输出 −1。
若一个由图中所有点构成的序列 A 满足：对于图中的每条边 (x,y)，x 在 A 中都出现在 y之前，则称 A是该图的一个拓扑序列。

输入格式
第一行包含两个整数 n和 m。
接下来 m 行，每行包含两个整数 x 和 y，表示存在一条从点 x 到点 y 的有向边 (x,y)。

输出格式
共一行，如果存在拓扑序列，则输出任意一个合法的拓扑序列即可。
否则输出 −1。

数据范围
1≤n,m≤1e5

输入样例：
3 3
1 2
2 3
1 3

输出样例：
1 2 3

 */

//public class Main {
//    static int n, m;//dots,edges
//    static ArrayList<ArrayList<Integer>> graph = new ArrayList<>();
//    static int[] inDegree = new int[10010];
//    static ArrayList<Integer> path = new ArrayList<>();
//
//    static void addEdge(int v, int w) {
//        graph.get(v).add(w);
//    }
//
//    static boolean topLogicalSort() {
//        Queue<Integer> q = new LinkedList<>();
//        for (int i = 1; i <= n; i++) {
//            if (inDegree[i] == 0) q.add(i);
//        }
//        while (!q.isEmpty()) {
//            int u = q.poll();
//            path.add(u);
//            for (int v : graph.get(u)) {
//                inDegree[v]--;
//                if (inDegree[v] == 0) q.add(v);
//            }
//        }
//        return path.size() == n;
//    }
//
//    public static void main(String[] args) {
//        Scanner sc = new Scanner(System.in);
//        for (int i = 0; i < 10005; i++) {
//            graph.add(new ArrayList<>());
//        }
//        n = sc.nextInt();
//        m = sc.nextInt();
//        for (int i = 0; i < m; i++) {
//            int from = sc.nextInt(), to = sc.nextInt();
//            graph.get(from).add(to);
//            inDegree[to]++;
//        }
//        if (topLogicalSort()) {
//            for (int i : path)
//                System.out.print(i + " ");
//        } else {
//            System.out.println("-1");
//        }
//    }
//}


/*
八数码
在一个 3×3 的网格中，1∼8 这 8个数字和一个 x 恰好不重不漏地分布在这 3×3 的网格中。
例如：
1 2 3
x 4 6
7 5 8
在游戏过程中，可以把 x 与其上、下、左、右四个方向之一的数字交换（如果存在）。
我们的目的是通过交换，使得网格变为如下排列（称为正确排列）：
1 2 3
4 5 6
7 8 x
例如，示例中图形就可以通过让 x 先后与右、下、右三个方向的数字交换成功得到正确排列。
交换过程如下：
1 2 3    1 2 3    1 2 3    1 2 3
x 4 6 -> 4 x 6 -> 4 5 6 -> 4 5 6
7 5 8    7 5 8    7 x 8    7 8 x
现在，给你一个初始网格，请你求出得到正确排列至少需要进行多少次交换。

输入格式
输入占一行，将 3×3的初始网格描绘出来。
例如，如果初始网格如下所示：
1 2 3
x 4 6
7 5 8
则输入为：1 2 3 x 4 6 7 5 8

输出格式
输出占一行，包含一个整数，表示最少交换次数。
如果不存在解决方案，则输出 −1。

输入样例：
2 3 4 1 5 x 7 6 8

输出样例
19
 */
public class Main {
    static int minTimes;

    static boolean bfs(String start) {
        HashMap<String, Integer> dist = new HashMap<>();
        dist.put(start, 0);
        Queue<String> q = new LinkedList<>();
        q.add(start);
        String end = "12345678x";
        while (!q.isEmpty()) {
            String s = q.poll();
            int d = dist.get(s);
            if (s.equals(end)) {
                minTimes = d;
                return true;
            }
            int[] dx = {-1, 1, 0, 0};
            int[] dy = {0, 0, -1, 1};
            int idx = s.indexOf('x');
            int x = idx / 3, y = idx % 3;
            for (int i = 0; i < 4; i++) {
                int nx = x + dx[i], ny = y + dy[i];
                if (nx >= 0 && nx < 3 && ny >= 0 && ny < 3) {
                    int nidx = nx * 3 + ny;
                    StringBuilder sb = new StringBuilder(s);
                    //交换字符
                    char temp = sb.charAt(idx);
                    sb.setCharAt(idx, sb.charAt(nidx));
                    sb.setCharAt(nidx, temp);
                    String ns = sb.toString();
                    //如过ns未在dist出现过，则加入
                    if (!dist.containsKey(ns)) {
                        q.add(ns);
                        dist.put(ns, d + 1);
                    }
                }
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String start = sc.nextLine();
        start = start.replaceAll(" ", "");//除去所有空格
        if (bfs(start)) System.out.println(minTimes);
        else System.out.println(-1);
    }
}